package prototyping.server;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.Date;

import prototyping.client.AbstractMessage;
import prototyping.client.ChatMessage;
import prototyping.client.HelpMessage;

public class ClientListener extends Thread {

	// TODO WHy extra socket?? the socket where to listen/talk to
	private Socket socket;
	private ObjectInputStream sInput;
	private ObjectOutputStream sOutput;
	// TODO Should be better solution for this id
	private int id;
	// TODO Why?? username is in client or abstract message. the Username of the
	// Client. Try OOP!!
	private String username;
	// The message to recieve.
	private AbstractMessage msg;
	// TDOD Change to GregorianCalendar??
	private String date;
	private Server server;

	public ClientListener(Socket socket, Server server, int uniqueId) {
		// TODO UniqueID comes from Server Class. Make param. a unique id
		// TODO Why is the socket passed as param from Server to this?
		this.id = ++uniqueId;
		this.socket = socket;
		this.server = server;
		/*
		 * Creating both Data Streams
		 */
		try {
			sOutput = new ObjectOutputStream(socket.getOutputStream());
			sInput = new ObjectInputStream(socket.getInputStream());
			HelpMessage hmsg = (HelpMessage) sInput.readObject();
			username = hmsg.getUser();
		} catch (IOException e) {
			return;
		} catch (ClassNotFoundException e) {
			return;
		}
		// TODO Use GregorianCalendar instead.
		date = new Date().toString() + "\n";
	}

	public void run() {
		// TODO Should be looping until Account logs out.
		boolean keepGoing = true;
		while (keepGoing) {
			try {
				// TODO Should check for ChatMessage or HelpMessage??
				msg = (AbstractMessage) sInput.readObject();
			} catch (IOException ioe) {
				break;
			} catch (ClassNotFoundException cnfe) {
				break;
			}
			server.broadcast(msg);
		}
		server.remove(id);
		close();
	}

	private void close() {
		try {
			if (sOutput != null) {
				sOutput.close();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		try {
			if (sInput != null) {
				sInput.close();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		try {
			if (socket != null) {
				socket.close();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/*
	 * Write a String to the Client output stream
	 * Should be some kind of Abstract Message
	 */
	public boolean writeMsg(AbstractMessage amsg) {
		if (!socket.isConnected()) {
			close();
			return false;
		}
		try {
			sOutput.writeObject(amsg);
		}
		catch (IOException e) {
			e.printStackTrace();
		}
		return true;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public Socket getSocket() {
		return socket;
	}

	public void setSocket(Socket socket) {
		this.socket = socket;
	}

	public ObjectInputStream getsInput() {
		return sInput;
	}

	public void setsInput(ObjectInputStream sInput) {
		this.sInput = sInput;
	}

	public ObjectOutputStream getsOutput() {
		return sOutput;
	}

	public void setsOutput(ObjectOutputStream sOutput) {
		this.sOutput = sOutput;
	}

	public long getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

}
